package com.ygqh.baby.service.impl;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.JsonResult;
import com.foxinmy.weixin4j.model.MediaItem;
import com.foxinmy.weixin4j.model.MediaUploadResult;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.model.WeixinAccount;
import com.foxinmy.weixin4j.mp.api.*;
import com.foxinmy.weixin4j.mp.message.NotifyMessage;
import com.foxinmy.weixin4j.mp.model.*;
import com.foxinmy.weixin4j.mp.token.WeixinTicketCreator;
import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.tuple.MassTuple;
import com.foxinmy.weixin4j.type.MediaType;
import com.foxinmy.weixin4j.type.TicketType;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.util.WeixinErrorUtil;
import com.ygqh.baby.ao.AppType;
import com.ygqh.baby.ao.FileType;
import com.ygqh.baby.constant.Constant;
import com.ygqh.baby.model.WxJsapiSignature;
import com.ygqh.baby.model.wx.WxButton;
import com.ygqh.baby.po.YgPlatform;
import com.ygqh.baby.service.FileService;
import com.ygqh.baby.service.WxMpAuthorityService;
import com.ygqh.baby.service.WxTokenStorager;
import com.ygqh.baby.service.YgPlatformService;
import com.ygqh.baby.service.wechat.api.YgMenuApi;
import com.ygqh.baby.service.wechat.api.YgUserApi;
import com.ygqh.baby.service.wechat.model.WxQRParameter;
import com.ygqh.baby.utils.*;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.text.MessageFormat;
import java.util.List;
import java.util.Map;

@Service
public class WxMpAuthorityServiceImpl implements WxMpAuthorityService {

    protected final Logger logger = Logger.getLogger(this.getClass());

    @Value("${micro.msg.appId}")
    protected String appId;
    @Value("${micro.msg.secret}")
    protected String appSecret;
    @Value("${micro.msg.customToken}")
    protected String customToken;
    @Value("${micro.msg.encodingAESKey}")
    protected String encodingAESKey;
    @Value("${micro.msg.oauth2.url}")
    protected String wxAuth2Url;
    @Value("${micro.msg.oauth2.redirect_uri}")
    protected String wxRedirectUri;
    @Autowired
    private WxTokenStorager tokenStorager;
    @Autowired
    private FileService fileService;
    @Autowired
    private YgPlatformService ygPlatformService;

    @Override
    public String findCustomToken() {
        return customToken;
    }

    @Override
    public TokenHolder findTokenHolder() {
        WeixinTokenCreator weixinTokenCreator = new WeixinTokenCreator(appId, appSecret);
        return new TokenHolder(weixinTokenCreator, tokenStorager);
    }

    @Override
    public TokenHolder findTokenHolder(String platformNo) {
        if (StringUtils.isBlank(platformNo) || Constant.YIIGOO_PLATFORM_NO.equals(platformNo)) {
            return findTokenHolder();
        }
        YgPlatform platform = ygPlatformService.findByPlatformNo(platformNo, AppType.WeChat);
        WeixinTokenCreator weixinTokenCreator = new WeixinTokenCreator(platform.getAppId(), platform.getSecret());
        return new TokenHolder(weixinTokenCreator, tokenStorager);
    }

    @Override
    public String wxAuth2UrlFormat(String redirectUrl) {
        if (redirectUrl.startsWith("http:")) {
            redirectUrl = getShortUrl(redirectUrl);
        }
        return MessageFormat.format(wxAuth2Url, appId, wxRedirectUri, redirectUrl);
    }

    @Override
    public List<Menu> getAllMenu() throws WeixinException {
        return getAllMenu(null);
    }

    @Override
    public List<Menu> getAllMenu(String platformNo) throws WeixinException {
        MenuApi menuApi = new MenuApi(findTokenHolder(platformNo));
        return menuApi.getAllMenu();
    }

    @Override
    public void deleteCustomMenu() throws WeixinException {
        MenuApi menuApi = new MenuApi(findTokenHolder());
        menuApi.deleteMenu();
    }

    @Override
    public Token findTicket(TicketType ticketType) throws WeixinException {
        WeixinTicketCreator weixinTicketCreator = new WeixinTicketCreator(appId, ticketType, findTokenHolder());

        TokenHolder tokenHolder = new TokenHolder(weixinTicketCreator, tokenStorager);

        return tokenHolder.getToken();
    }

    @Override
    public WxJsapiSignature generateJsapiSignature(String url) throws WeixinException {
        String jsapiTicket = findTicket(TicketType.jsapi).getAccessToken();

        String str = YgStringUtils.getRandomString(16);
        String timestamp = Long.toString(System.currentTimeMillis() / 1000);// DateConvertUtils.format(new
        // Date(),
        // "yyyyMMddHHmm");
        StringBuilder sb = new StringBuilder();
        sb.append("jsapi_ticket=");
        sb.append(jsapiTicket);
        sb.append("&noncestr=");
        sb.append(str);
        sb.append("&timestamp=");
        sb.append(timestamp);
        sb.append("&url=");
        sb.append(url);
        logger.info("str:" + sb.toString());
        WxJsapiSignature wxJsapiSignature = new WxJsapiSignature();
        wxJsapiSignature.setAppId(appId);
        wxJsapiSignature.setNonceStr(str);
        wxJsapiSignature.setTimestamp(timestamp);

        MessageDigest md = null;
        String tmpStr = null;

        try {
            md = MessageDigest.getInstance("SHA-1");
            // 将三个参数字符串拼接成一个字符串进行sha1加密
            byte[] digest = md.digest(sb.toString().getBytes());
            tmpStr = YgStringUtils.byteToStr(digest);
            logger.info("字节转换成十六进制字符串");
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (tmpStr != null) {
            wxJsapiSignature.setSignature(tmpStr);
            return wxJsapiSignature;
        }

        return null;
    }

    @Override
    public User findUserInfo(String code) throws WeixinException {
        // OauthApi oauthApi = new OauthApi(new WeixinAccount(appId,
        // appSecret));
        // OauthToken oauthToken = oauthApi.getOauthToken(code);
        logger.debug("ip= " + WebUtils.getLocalIpAddr() + ";code= " + code);
        User user = null;
        try {
            String authUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId + "&secret="
                    + appSecret + "&code=" + code + "&grant_type=authorization_code";
            String authRes = HttpUtil.get(authUrl);

            checkJson(authRes);
            OauthToken oauthToken = JSON.parseObject(authRes, OauthToken.class);
            String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + oauthToken.getAccessToken()
                    + "&openid=" + oauthToken.getOpenId() + "&lang=zh_CN";
            String res = HttpUtil.get(url);
            checkJson(res);
            user = JSON.parseObject(res, User.class);
        } catch (Exception e) {
            logger.error(e.getMessage() + ";code=" + code);
            e.printStackTrace();
            throw new WeixinException(e.getMessage());
        }
        return user;
    }

    protected void checkJson(String res) throws WeixinException {
        if (!StringUtil.isBlank(res)) {
            JsonResult jsonResult = JSON.parseObject(res, JsonResult.class);
            if (jsonResult.getCode() != 0) {
                if (StringUtil.isBlank(jsonResult.getDesc())) {
                    jsonResult.setDesc(WeixinErrorUtil.getText(Integer.toString(jsonResult.getCode())));
                }
                throw new WeixinException(Integer.toString(jsonResult.getCode()), jsonResult.getDesc());
            }
        } else {

            throw new WeixinException("-1", "微信接口异常，返回值为  " + res);
        }
    }

    @Override
    public OauthToken findOauthToken(String code) throws WeixinException {
        OauthApi oauthApi = new OauthApi(new WeixinAccount(appId, appSecret));
        OauthToken oauthToken = oauthApi.getOauthToken(code);
        return oauthToken;
    }

    @Override
    public String getAuthorizeURL(String state, String scopes, String redirectUri) throws WeixinException {
        OauthApi oauthApi = new OauthApi(new WeixinAccount(appId, appSecret));
        String authorizeURL = oauthApi.getAuthorizeURL(appId, redirectUri, state, scopes);
        return authorizeURL;
    }

    @Override
    public String findQrCodeUrl(String sourceCode) throws WeixinException {
        QRParameter qrParameter = QRParameter.createPermanenceStr(sourceCode);
        return findQrCodeUrl(qrParameter.getContent().getBytes());
    }

    private String findQrCodeUrl(byte[] bytes) throws WeixinException {
        TokenHolder tokenHolder = this.findTokenHolder();
        String accessToken = tokenHolder.getAccessToken();
        String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + accessToken;
        String codeUrl = null;
        try {
            URL url1 = new URL(url);
            HttpURLConnection con = (HttpURLConnection) url1.openConnection();
            con.setDoOutput(true);
            // POST方式
            con.setRequestMethod("POST");
            // 输出流，写数据
            OutputStream os = con.getOutputStream();
            os.write(bytes);
            // 读取结果
            BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String line;
            System.out.println("-----开始读取----");
            while ((line = reader.readLine()) != null) {
                ObjectMapper mapper = new ObjectMapper();
                Map map = mapper.readValue(line, Map.class);
                String ticket = (String) map.get("ticket");
                if (StringUtils.isNotEmpty(ticket)) {
                    ticket = URLEncoder.encode(ticket, "UTF-8");
                    codeUrl = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" + ticket;
                }
                System.err.println(codeUrl);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return codeUrl;
    }

    @Override
    public String findTempQrCodeUrl(String sourceCode, int expireSeconds) throws WeixinException {
        WxQRParameter qrParameter = WxQRParameter.createTemporary(expireSeconds, sourceCode);
        return findQrCodeUrl(qrParameter.getContent().getBytes());
    }

    @Override
    public String getShortUrl(String url) {
        TokenHolder tokenHolder = this.findTokenHolder();
        HelperApi HelperApi = new HelperApi(tokenHolder);
        try {
            return HelperApi.getShorturl(url);
        } catch (WeixinException e) {
            e.printStackTrace();
        }
        return url;

    }

    @Override
    public User getUserInfo(String openId) throws WeixinException {
        return getUserInfo(openId, null);
    }

    @Override
    public User getUserInfo(String openId, String platformNo) throws WeixinException {
        UserApi userApi = new UserApi(this.findTokenHolder(platformNo));
        return userApi.getUser(openId);
    }

    @Override
    public JsonResult sendKeFuMsg(NotifyMessage notify) throws WeixinException {

        NotifyApi notifyAPI = new NotifyApi(this.findTokenHolder());

        return notifyAPI.sendNotify(notify);
    }

    @Override
    public List<MediaItem> getAllMaterialMedia(MediaType mediaType) throws WeixinException {
        MediaApi mediaApi = new MediaApi(this.findTokenHolder());
        return mediaApi.listAllMaterialMedia(mediaType);
    }

    @Override
    public List<User> getUsers(String[] openIds) throws WeixinException {
        UserApi userApi = new UserApi(this.findTokenHolder());
        return userApi.getUsers(openIds);
    }

    @Override
    public String getQrCodeUrl(String url, HttpServletRequest request, FileType fileType) {
        String path = request.getRealPath("/");
        String realPath = path + "/" + fileType.name();
        String fileName = System.currentTimeMillis() + ".jpg";
        String qrcodeUrl = "";
        try {
            File file = QRCodeUtil.getFile(url, realPath, fileName);
            if (!StringUtil.isBlank(realPath)) {

                String ext = fileName.split("\\.")[1];
                qrcodeUrl = fileService.uploadImage(file, new FileType[]{FileType.QrCode}, ext, true, request);

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 生成推广短连接
        return qrcodeUrl;
    }

    @Override
    public void publishCustomMenu(List<WxButton> listMenus) throws WeixinException {
        YgMenuApi menuApi = new YgMenuApi(findTokenHolder());
        JsonResult result = menuApi.createMenuNew(listMenus);
        logger.debug(result.toString());
    }

    @Override
    public void addKFAccount() {
        CustomApi customApi = new CustomApi(this.findTokenHolder());
    }

    @Override
    public void publishCustomMenu(String menuJson) throws WeixinException {
        publishCustomMenu(menuJson, null);
    }

    @Override
    public void publishCustomMenu(String menuJson, String platformNo) throws WeixinException {
        YgMenuApi menuApi = new YgMenuApi(findTokenHolder(platformNo));
        JsonResult result = menuApi.createMenu(menuJson);
        logger.debug(result.toString());
    }

    @Override
    public Following findUserList(String nextOpenId) throws WeixinException {
        UserApi userApi = new UserApi(this.findTokenHolder());
        Following following = userApi.getFollowing(nextOpenId);
        return following;
    }

    @Override
    public void sendAllMsg(MassTuple tuple, boolean isToAll, int groupId) throws WeixinException {
        MassApi api = new MassApi(this.findTokenHolder());
        String[] massByGroupId = api.massByGroupId(tuple, isToAll, groupId);

        System.out.println("msg_id=" + massByGroupId[0] + ";msg_data_id" + massByGroupId[1]);
    }

    @Override
    public MediaUploadResult addMaterial() {
        MediaApi mediaApi = new MediaApi(this.findTokenHolder());
        InputStream inputStream = ImageUtils.getInputStream("http://yiigoo-tmp.oss-cn-shanghai.aliyuncs.com/qrcode/2019/01/11/1547176061765917026.jpg");
        try {
            return mediaApi.uploadMedia(true, inputStream, "新年有礼二维码");
        } catch (WeixinException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public int getGroupId(String groupName) throws WeixinException {
        GroupApi api = new GroupApi(this.findTokenHolder());
        List<Group> groups = api.getGroups();
        System.out.println(groups.toString());
        for (Group group : groups) {
            if (group.getName().equals(groupName)) {
                return group.getId();
            }
        }
        return 0;
    }

    @Override
    public List<User> findAllFollowing() throws WeixinException {
        UserApi userApi = new UserApi(this.findTokenHolder());
        List<User> following = userApi.getAllFollowing();
        return following;
    }

    @Override
    public List<String> findAllOpenIds() throws WeixinException {
        YgUserApi api = new YgUserApi(this.findTokenHolder());
        return api.getAllOpenIds();
    }

}
